import java.awt.Image;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;

import javax.media.opengl.GL;
import javax.media.opengl.glu.GLU;

import com.sun.opengl.util.texture.Texture;
import com.sun.opengl.util.texture.TextureData;
import com.sun.opengl.util.texture.TextureIO;

public class Screen {
	GL gl;
	GLU glu;
	private int shaderprogram, cloud1[],cloud2[],screen_noise[],depth1[],depth2[];
	private int vert_shader, frag_shader;
	public Vector3D center;
	private float radius;
	private float flash_weight;
	public static int draw_info, frames_after_draw;
	private int num;
	Texture boxTexture1,boxTexture2,boxTexture3,boxTexture4,boxTexture5;
	float cur_time, start_time;
	
	public Screen(GL gl_, GLU glu_){
		gl=gl_;
		glu=glu_;
		cloud1 = new int[1];
		cloud2 = new int[1];
		depth1 = new int[1];
		depth2 = new int[1];
		screen_noise = new int[1];
		draw_info = 0;
		frames_after_draw = 200;
		init();
		loadShader();
		CreateTexture(null);
	}

	private void init(){
		flash_weight = 0.0f;
		num = 1;
		radius = 0.001f;//sprite radius
		start_time = System.currentTimeMillis();
		center = new Vector3D();
		center.setX(-10f);
		center.setY(150f); //lowest corner of spread NOT CENTER not recommended to touch!
		center.setZ(0f);
	}
	private void CreateTexture(Image image)
	 {

		 
			URL imageURL1= this.getClass().getResource(
					 "start_scr.png");
		        
			 TextureData data1=null;
			 try {
				 data1 = TextureIO.newTextureData(
						 imageURL1.openStream(),false, "png");
				 boxTexture2 = TextureIO.newTexture(data1);
			 } catch (IOException exc) {
				 exc.printStackTrace();
				 System.exit(1);
			 }       
			 gl.glEnable(GL.GL_TEXTURE_2D);
			 
			 gl.glGenTextures(1,cloud2, 0);
			 gl.glBindTexture(GL.GL_TEXTURE_2D, cloud2[0]);
			 gl.glTexImage2D(GL.GL_TEXTURE_2D, 0,GL.GL_RGBA,data1.getWidth(),data1.getHeight(),0,GL.GL_RGBA,
					 GL.GL_UNSIGNED_BYTE,data1.getBuffer());
		
			 URL imageURL2= this.getClass().getResource(
					 "noise.png");
		        
			 TextureData data2=null;
			 try {
				 data2 = TextureIO.newTextureData(
						 imageURL2.openStream(),false, "png");
				 boxTexture3 = TextureIO.newTexture(data2);
			 } catch (IOException exc) {
				 exc.printStackTrace();
				 System.exit(1);
			 }       
			 gl.glEnable(GL.GL_TEXTURE_2D);
			 
			 gl.glGenTextures(1,screen_noise, 0);
			 gl.glBindTexture(GL.GL_TEXTURE_2D, screen_noise[0]);
			 gl.glTexImage2D(GL.GL_TEXTURE_2D, 0,GL.GL_RGBA,data2.getWidth(),data2.getHeight(),0,GL.GL_RGBA,
					 GL.GL_UNSIGNED_BYTE,data2.getBuffer());
			 
				URL imageURL= this.getClass().getResource(
						 "start_scr.png");
			        
				 TextureData data=null;
				 try {
					 data = TextureIO.newTextureData(
							 imageURL.openStream(),false, "png");
					 boxTexture1 = TextureIO.newTexture(data);
				 } catch (IOException exc) {
					 exc.printStackTrace();
					 System.exit(1);
				 }       
				 gl.glEnable(GL.GL_TEXTURE_2D);
				 
				 gl.glGenTextures(1,cloud1, 0);
				 gl.glBindTexture(GL.GL_TEXTURE_2D, cloud1[0]);
				 gl.glTexImage2D(GL.GL_TEXTURE_2D, 0,GL.GL_RGBA,data.getWidth(),data.getHeight(),0,GL.GL_RGBA,
						 GL.GL_UNSIGNED_BYTE,data.getBuffer());
			 URL imageURL3= this.getClass().getResource(
					 "star.png");
		        
			 TextureData data3=null;
			 try {
				 data3 = TextureIO.newTextureData(
						 imageURL3.openStream(),false, "png");
				 boxTexture4 = TextureIO.newTexture(data3);
			 } catch (IOException exc) {
				 exc.printStackTrace();
				 System.exit(1);
			 }       
			 gl.glGenTextures(1,depth1, 0);
			 gl.glBindTexture(GL.GL_TEXTURE_2D, depth1[0]);
			 gl.glTexImage2D(GL.GL_TEXTURE_2D, 0,GL.GL_DEPTH_COMPONENT,data2.getWidth(),data2.getHeight(),0,GL.GL_DEPTH_COMPONENT,
					 GL.GL_UNSIGNED_BYTE,null);
			 
      
			 gl.glGenTextures(1,depth2, 0);
			 gl.glBindTexture(GL.GL_TEXTURE_2D, depth2[0]);
			 gl.glTexImage2D(GL.GL_TEXTURE_2D, 0,GL.GL_DEPTH_COMPONENT,data2.getWidth(),data2.getHeight(),0,GL.GL_DEPTH_COMPONENT,
					 GL.GL_UNSIGNED_BYTE,null);
			 
			 /*gl.glGenTextures(1,depth1, 0);
			 gl.glBindTexture(GL.GL_TEXTURE_2D, depth1[0]);
			 gl.glTexImage2D(GL.GL_TEXTURE_2D, 0,GL.GL_DEPTH_COMPONENT,2000,2000,0,GL.GL_DEPTH_COMPONENT,
					 GL.GL_UNSIGNED_BYTE,null);
			 
			 gl.glGenTextures(1,depth2, 0);
			 gl.glBindTexture(GL.GL_TEXTURE_2D, depth2[0]);
			 gl.glTexImage2D(GL.GL_TEXTURE_2D, 0,GL.GL_DEPTH_COMPONENT,2000,2000,0,GL.GL_DEPTH_COMPONENT,
					 GL.GL_UNSIGNED_BYTE,null);*/
	}
	
	 private void loadShader(){
		 vert_shader = gl.glCreateShader(GL.GL_VERTEX_SHADER);
	        frag_shader = gl.glCreateShader(GL.GL_FRAGMENT_SHADER);
	        
	        BufferedReader brv = null;
			try {
				brv = new BufferedReader(
						new FileReader(
								"src/screen.vert"));
			} catch (FileNotFoundException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
	        String vsrc = "";
	        String line;
	        try {
				while ((line=brv.readLine()) != null) {
				  vsrc += line + "\n";
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        gl.glShaderSource(vert_shader, 1,
	        		new String[] {vsrc}, (int[])null, 0);
	        gl.glCompileShader(vert_shader);
	        
	        BufferedReader brf = null;
			try {
				brf = new BufferedReader(
						new FileReader(
								"src/screen.frag"));
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        String fsrc = "";
	        String lines;
	        try {
				while ((lines=brf.readLine()) != null) {
				  fsrc += lines + "\n";
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        gl.glShaderSource(frag_shader, 1,
	        		new String[] {fsrc}, (int[])null, 0);
	        gl.glCompileShader(frag_shader);
	        
	        shaderprogram = gl.glCreateProgram();
	        gl.glAttachShader(shaderprogram, vert_shader);
	        gl.glAttachShader(shaderprogram, frag_shader);
	        gl.glLinkProgram(shaderprogram);
	        gl.glValidateProgram(shaderprogram);
	 }
	 public void shot(int width, int height) {
		
	}
	 private void setShader(float width, float height, float brightness){
	   // System.out.println("num = " + num);
		    
		    gl.glActiveTexture(GL.GL_TEXTURE3);
		    if(MyJoglCanvas.render_scene) gl.glBindTexture(GL.GL_TEXTURE_2D,cloud2[0]-1);
		    else gl.glBindTexture(GL.GL_TEXTURE_2D,cloud2[0]-1);
		    if(num == 2 && MyJoglCanvas.render_scene) {
		    	gl.glCopyTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB,0,0, (int)width,(int)height,0);
		    }
		    
		    
		    gl.glActiveTexture(GL.GL_TEXTURE4);
		    gl.glBindTexture(GL.GL_TEXTURE_2D,depth1[0]-1);
		    if(num == 1 && MyJoglCanvas.render_scene) {
		    gl.glCopyTexImage2D (GL.GL_TEXTURE_2D, 0,  GL.GL_DEPTH_COMPONENT, 0, 0, (int)width, (int)height, 0 );
		    }
		    gl.glActiveTexture(GL.GL_TEXTURE5);
		    gl.glBindTexture(GL.GL_TEXTURE_2D,depth2[0]-1);
		    if(num == 2 && MyJoglCanvas.render_scene) {
		    	gl.glCopyTexImage2D (GL.GL_TEXTURE_2D, 0,  GL.GL_DEPTH_COMPONENT, 0, 0, (int)width, (int)height, 0 );
		    }
		    gl.glActiveTexture(GL.GL_TEXTURE6);
		    if(MyJoglCanvas.render_scene) gl.glBindTexture(GL.GL_TEXTURE_2D,screen_noise[0]-1);
		    else gl.glBindTexture(GL.GL_TEXTURE_2D,screen_noise[0]-1);
		    gl.glActiveTexture(GL.GL_TEXTURE7);
		    if(MyJoglCanvas.render_scene)  gl.glBindTexture(GL.GL_TEXTURE_2D,cloud1[0]-1);
		    else gl.glBindTexture(GL.GL_TEXTURE_2D,cloud1[0]-1);
		    if(num == 1 && MyJoglCanvas.render_scene) {
		    	gl.glCopyTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB,0,0, (int)width,(int)height,0);
		    }
		    gl.glUniform1i(gl.glGetUniformLocation(
	        		shaderprogram, "tex1"), 7);
		    gl.glUniform1i(gl.glGetUniformLocation(
	        		shaderprogram, "tex2"), 3);
		    gl.glUniform1i(gl.glGetUniformLocation(
	        		shaderprogram, "screen_noise"), 6);
		    gl.glUniform1i(gl.glGetUniformLocation(
	        		shaderprogram, "draw_info"), draw_info);
		    gl.glUniform1i(gl.glGetUniformLocation(
	        		shaderprogram, "frames"), frames_after_draw);
		    gl.glUniform1i(gl.glGetUniformLocation(
	        		shaderprogram, "depth_map1"), 4);
		    gl.glUniform1i(gl.glGetUniformLocation(
	        		shaderprogram, "depth_map2"), 5);
	        gl.glUniform1i(gl.glGetUniformLocation(
	        		shaderprogram, "num"), num);
	        gl.glUniform1f(gl.glGetUniformLocation(
	        		shaderprogram, "brightness"), brightness);
	        gl.glUniform1f(gl.glGetUniformLocation(
	        		shaderprogram, "flash"), flash_weight);
	        gl.glUniform1f(gl.glGetUniformLocation(
	        		shaderprogram, "blur"), MyJoglCanvas.blur);
	        gl.glUniform1f(gl.glGetUniformLocation(
	        		shaderprogram, "rnd_x"), Explosion.rnd());
	        gl.glUniform1f(gl.glGetUniformLocation(
	        		shaderprogram, "rnd_y"), Explosion.rnd());
	        gl.glUniform1f(gl.glGetUniformLocation(
	        		shaderprogram, "Width"), width);
	        gl.glUniform1f(gl.glGetUniformLocation(
	        		shaderprogram, "Height"), height);
	        gl.glUniform4f(gl.glGetUniformLocation(
	        		shaderprogram, "sun"), Atmosphere.sun.x()+Camera.pos.x, Atmosphere.sun.y()+Camera.pos.y, Atmosphere.sun.z()+Camera.pos.z,1.0f);
	 }
	 public void draw(Camera player,float width, float height,float radius2,float brightness,boolean flash) {
		 		//System.out.println(flash);
		 		if(draw_info != 0) {
		 			if(frames_after_draw < 50) frames_after_draw++;
		 			else if(draw_info != 4)draw_info = 0;
		 		}
		 		cur_time = (System.currentTimeMillis() - start_time);
		 		if(flash) flash_weight = 0.8f;
		 		radius = radius2;
		 		float w, h;
		 		w = width/height*radius;
		 		h = radius;
		 		float yaw = player.yaw;
		 		float pitch = player.pitch;
		 		center.setXYZ(player.pos.x,player.pos.y,player.pos.z);
			    Vector3D point1 = new Vector3D(-2f,-w,-h);
			    Vector3D point2 = new Vector3D(-2f,w,-h);
			    Vector3D point3 = new Vector3D(-2f,w,h);
			    Vector3D point4 = new Vector3D(-2f,-w,h);

			    Matrix4x4 maty = new Matrix4x4();
			    Matrix4x4 matz = new Matrix4x4();
			    yaw = -yaw;  
			    pitch = -pitch;
			    maty = Matrix4x4.set((float)Math.cos(pitch),0,(float)Math.sin(pitch),0,
		                   0,1,0,0,
		                   (float)-Math.sin(pitch),0,(float)Math.cos(pitch),0,
		                   0,0,0,1);
		    

			    matz = Matrix4x4.set((float)Math.cos(yaw+Atmosphere.pi),(float)-Math.sin(yaw+Atmosphere.pi),0,0,
		    		(float)Math.sin(yaw+Atmosphere.pi),(float)Math.cos(yaw+Atmosphere.pi),0,0,
		                   0,0,1,0,
		                   0,0,0,1);
			    
			    point1 = Matrix4x4.mult(Matrix4x4.mult(matz,maty),point1);
			    point2 = Matrix4x4.mult(Matrix4x4.mult(matz,maty),point2);
			    point3 = Matrix4x4.mult(Matrix4x4.mult(matz,maty),point3);
			    point4 = Matrix4x4.mult(Matrix4x4.mult(matz,maty),point4);
			    gl.glUseProgram(shaderprogram);

			    setShader(width,height,brightness);
			    num++;
			    if(num > 2) num = 1;
			    gl.glDisable(GL.GL_CULL_FACE);
			    gl.glBegin(GL.GL_QUADS);
			    	gl.glTexCoord2d(0,0);
			    	gl.glVertex3f(point1.x()+center.x(),point1.y()+center.y(),point1.z()+center.z());

			    	gl.glTexCoord2d(1,0);
			    	gl.glVertex3f(point2.x()+center.x(),point2.y()+center.y(),point2.z()+center.z());

			    	gl.glTexCoord2d(1,1);
			    	gl.glVertex3f(point3.x()+center.x(),point3.y()+center.y(),point3.z()+center.z());

			    	gl.glTexCoord2d(0,1);
			    	gl.glVertex3f(point4.x()+center.x(),point4.y()+center.y(),point4.z()+center.z());
			    gl.glEnd();
			    gl.glEnable(GL.GL_CULL_FACE);
			    gl.glUseProgram(0);
			    if(flash_weight >= 0.0f) flash_weight -= 0.03f;
	}
}